#include <p18f46k22.h>
#include <usart.h>
#include "l70.h"

#pragma config FOSC = HSHP //HS oscillator (high power > 16 MHz)
#pragma config WDTEN = OFF, LVP = OFF, MCLRE = EXTMCLR  //Watchdog timer off, single-supply ICSP disabled, MCLR pin enabled

#pragma code

typedef unsigned char Uint8;

void parser_gps(Uint8 c);

void InterruptHandlerHigh (void);

Uint8 trame_gps[77];
//Uint8 trame_test[] = "$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68$GPGGA,064036.289,4836.5375,N,00740.9373,E,1,04,3.2,200.2,M,,,,0000*0E$GPGSA,A,3,,,,,,16,18,,22,24,,,3.3,2.2,1.1*4G";


#pragma code _vecteur_it_high = 0x08
void itHigh(void)
{
    _asm 
        goto InterruptHandlerHigh
    _endasm
}

#pragma interrupt InterruptHandlerHigh

void InterruptHandlerHigh (void)
{       
    if(PIR1bits.RC1IF)
    {
		Uint8 tamp;
		LATBbits.LATB3 = 1;
		tamp = getc1USART();
		parser_gps(tamp);
		LATBbits.LATB3 = 1;
    }

}


void main(void)
{
		//int i = 0;

        PORTC = 0x00;
        ANSELC = 0x00;

		//Enable interrupts
        INTCONbits.GIEH = 0;        //Enable all high priority interrupt
        INTCONbits.GIEH = 1;		//Enable all peripheral interrupt
		INTCONbits.GIEL = 1;		//Enable all MCU interrupt
	

        ANSELBbits.ANSB3 = 0;           
        TRISBbits.RB3 = 0;              
		
        init_gps_l70();
		
	/*	while(trame_test[i]!='\0')
		{
			parser_gps(trame_test[i]);
			i++;
		}*/
	    while(1);      
}void parser_gps(unsigned char c)
{
        typedef enum
        {
                WAIT_DOLLAR, 
                DOLLAR_RECEIVED, G_RECEIVED, P_RECEIVED,//debut de chaque trame
                R_RECEIVED,     M_RECEIVED,  //RMC
                G1_RECEIVED,    //G commun à GGA et GSA
                G2_RECEIVED,      //GA
                S_RECEIVED,      //SA
                WAIT_DATA, //attente de récup de données
                DATA_VALID, UTC, LAT,
                N_S, LONG, E_W, COG, SAT, ALTI,
                HDOP, PDOP,     VDOP            
        }state_e;
        
        typedef enum
        {
                UNDEFINED, GGA, RMC, GSA
        }type_frame;
        
        static state_e state = WAIT_DOLLAR;
        static type_frame typeOfFrame = UNDEFINED;
        
        static int nbre_comma = 0; //nombre de virgules par trame GPGGA ou GPRMC
        static int index = 0; //position dans le buffer trame_gps
        
        if(c== '$')
                state = DOLLAR_RECEIVED;        //Synchro sur le '$', quelque soit la trame... on se raccroche ici
        switch(state)
        {
                case WAIT_DOLLAR:       break;
                case DOLLAR_RECEIVED:   if(c== 'G')     state = G_RECEIVED;             break;
                case G_RECEIVED:                if(c== 'P')             state = P_RECEIVED;             break;
                case P_RECEIVED:                if(c== 'R')             state = R_RECEIVED;             
                                                                if(c== 'G')             state = G1_RECEIVED;    break;          
                
                case R_RECEIVED:                if(c== 'M')             state = M_RECEIVED;             break;
                case M_RECEIVED:                if(c== 'C'){      typeOfFrame = RMC;      state = WAIT_DATA;}           break;
    

                case G1_RECEIVED:               if(c== 'G')             state = G2_RECEIVED; if(c== 'S') state = S_RECEIVED;    break;
                
                case G2_RECEIVED:               
					if(c== 'A')
					{  
							if(index != 0)
	                        {
	                                typeOfFrame = GGA; 
	                                state = WAIT_DATA;
	                        }
	                        else
	                        {
	                                state = WAIT_DOLLAR;
	                        }
					}
                    break;                  
          
                case S_RECEIVED:               
					if(c== 'A')
					{
             			if(index != 0)
                        {
                                typeOfFrame = GSA; 
                                state = WAIT_DATA;
                        }
                        else
                        {
                                state = WAIT_DOLLAR;
                        }
					}
                    break; 
   
                case WAIT_DATA:                 
                        if(c== ',')     nbre_comma++;
                        
                        switch(nbre_comma)
                        {
                                        case 1: if(typeOfFrame== RMC) state = UTC; break;
                                        case 7: if(typeOfFrame== GGA) state = SAT; break;
                                        case 8: if(typeOfFrame== RMC) state = COG; break;
                                        case 9: if(typeOfFrame== GGA) state = ALTI; break;
                                        case 15: if(typeOfFrame== GSA) state = PDOP; break;
                                        default: break;
                        }
                break;
                
                case UTC:
                        if(c== ',')
                        {
                                state = DATA_VALID;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma++;
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case DATA_VALID: 
                        if(c== ',')
                        {
                                state = LAT;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma++;   
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case LAT:
                        if(c== ',')
                        {
                                state = N_S;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma++;   
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case N_S:
                        if(c== ',')
                        {
                                state = LONG;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma++;   
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case LONG:
                        if(c== ',')
                        {
                                state = E_W;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma++;   
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case E_W:
                        if(c== ',')
                        {
                                state = WAIT_DATA;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma++;   
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case SAT:
                        if(c== ',')
                        {
                                state = WAIT_DATA;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma++;   
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case COG:
                        if(c== ',')
                        {
                                state = WAIT_DOLLAR;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma = 0;
                                typeOfFrame = UNDEFINED;
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case ALTI:
                        if((c== ',') | (c=='.'))
                        {
                                state = WAIT_DOLLAR;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma = 0;
                                typeOfFrame = UNDEFINED;
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case PDOP:
                        if(c== ',')
                        {
                                state = HDOP;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma++;
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case HDOP:
                        if(c== ',')
                        {
                                state = VDOP;
                                trame_gps[index] = '|';
                                index++;
                                nbre_comma++;
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                case VDOP:
                        if(c== '*')
                        {
                                int i = 0;
								state = WAIT_DOLLAR;
                                nbre_comma = 0;
                                //traitement pour stocker la trame dans le buffer//
                                index = 0;
                                typeOfFrame = UNDEFINED;
                        }
                        else
                        {
                                trame_gps[index] = c;
                                index++;
                        }
                        break;
                default:        break;
        }
}
